package com.qz.stack.calculator.v1;

import com.qz.util.CalculatorUtils;

/**
 * @Description 实现加减乘除，多位运算，不能包括括号，小数点
 * @Author Flag
 * @Date: 2021/7/20 21:09
 * @Version: 1.0
 **/
public class CalculatorDome1 {
    public static void main(String[] args) {

        String expression = "1+2*3";

        //region 一、变量定义
        //定义数字的栈
        ArrayStack<Integer> numberStack = new ArrayStack<>(10);
        //定义符号的栈
        ArrayStack<Character> operationStack = new ArrayStack<>(10);
        //定义需要计算的字符串

        //定义字符串索引
        int index = 0;
        //定义字符串重组，用来解决多位数问题
        StringBuilder keepString = new StringBuilder();
        //endregion

        //region 二、核心逻辑
        //遍历需要计算的字符串
        while (index < expression.length()){
            //获取到需要计算字符串的第index(默认从0开始)个字符
            char c = expression.substring(index, index + 1).charAt(0);
            //如果是数字
            if(CalculatorUtils.isNumber(c)){
                //如果已经遍历到最后一位,则直接加入到栈
                if(index == expression.length()-1){
                    numberStack.push(c-48);
                } else {
                    //如果不是是最后一位
                    //先将这位数字添加到keepString字符串中
                    keepString.append(c);
                    //获取到index的下一位
                    c = expression.substring(index + 1, index + 2).charAt(0);
                    //如果c是数字(此时的c已经是第二位数字),则证明此时的数字不是个位数，继续遍历
                    while (CalculatorUtils.isNumber(c)){
                        //将第二位数字添加到其中
                        keepString.append(c);
                        //索引移动
                        index++;
                        //获取到下一位，然后继续判断你
                        if(index == expression.length()-1){
                            break;
                        }
                        c = expression.substring(index + 1, index + 2).charAt(0);
                    }
                    //运行到这里，即下一位肯定不是数字，即已经读取完改数
                    numberStack.push(Integer.parseInt(keepString.toString()));
                    //清空keepString
                    keepString.delete(0,keepString.length());
                }
            } else if(CalculatorUtils.isOper(c)) {
                //如果是符号
                //1.如果栈中是空的，则直接加入到栈
                if(operationStack.isEmpty()){
                    operationStack.push(c);
                } else {
                    //2.如果栈不是空的,取出元素，判断和当前字符的优先级
                    //现在的运算符级别
                    //之前的运算符级别
                    //如果现在的小于等于之前的，则计算
                    if(CalculatorUtils.priority(c) <= CalculatorUtils.priority(operationStack.peek())){
                        int lastNumber = numberStack.pop();
                        int beforLastNumber = numberStack.pop();
                        int cal = CalculatorUtils.cal(lastNumber, beforLastNumber, operationStack.pop());
                        numberStack.push(cal);
                        operationStack.push(c);
                    } else {
                        operationStack.push(c);
                    }
                }

            }
            index ++ ;
        }
        //endregion

        //region 三、最后计算
        while (true){
            if(numberStack.getTop() == 0 ){
                System.out.println(numberStack.pop());
                break;
            }
            Integer lastNumber = numberStack.pop();
            Integer beforeLastNumber = numberStack.pop();
            Character lastOperation = operationStack.pop();
            int cal = CalculatorUtils.cal(lastNumber, beforeLastNumber, lastOperation);
            numberStack.push(cal);
        }
        //endregion


    }
}


/**
 *
 */
class ArrayStack<T>{
    //定义栈的大小
    private int maxSize;
    //数组，数组模拟栈，数据就放在该数组中
    private Object[] stack;
    //top表示栈顶，初始化是-1
    private int top;

    /**
     * 构造方法
     * @param maxSize 栈的大小
     */
    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        stack = new Object[maxSize];
        top = -1;
    }

    /**
     * 判断栈是否满了
     * @return
     */
    public boolean isFull(){
        return top+1 == maxSize;
    }

    /**
     * 入栈
     * @param value 入栈的元素
     */
    public void push(T value){
        //判断栈是否满了
        if(this.isFull()){
            System.out.println("栈已经满了,不能再添加元素");
            return;
        }
        //将元素添加到栈中
        stack[++top] = value;
    }


    /**
     * 出栈
     * @return 出栈的元素
     */
    public T pop(){
        //判断栈是否为null
        if(this.isEmpty()){
            throw new RuntimeException("栈中没有元素");
        }
        //将元素出栈
        return (T) (stack[top--]);
    }



    /**
     * 显示栈的元素
     */
    public void show(){
        //判断栈是否为null
        if(this.isEmpty()){
            System.out.println("栈中无元素");
            return;
        }
        int index = top;
        while (index >= 0){
            System.out.println("元素:"+stack[index]);
            index--;
        }
    }

    /**
     * 判断栈是否为null
     * @return 结果
     */
    public boolean isEmpty(){
        return top == -1;
    }

    /**
     * 获取栈元素的数量
     * @return
     */
    public int getTop() {
        return top;
    }

    /**
     * 可以看到栈顶的元素，但是并不出栈
     * @return
     */
    public T peek(){
        return (T)stack[top];
    }
}


